package cn.kvchoi.reactor_nio.server;

import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

public class Reactor {
    private final Map<Integer, EventHandler> registeredHandlers = new ConcurrentHashMap<>();
    private final Selector demultiplexer;

    public Reactor() throws Exception {
        demultiplexer = Selector.open();
    }

    public void registerEventHandler(int eventType, EventHandler eventHandler) {
        registeredHandlers.put(eventType, eventHandler);
    }

    public void registerChannel(int eventType, SelectableChannel channel) throws Exception {
        channel.register(demultiplexer, eventType);
    }

    public void run() {
        try {
            // Loop indefinitely
            while (true) {
//                if (demultiplexer.selectNow() <= 0) {
                if (demultiplexer.select() <= 0) {
                    System.out.println("select...");
                    continue;
                }
                Set<SelectionKey> readyHandles = demultiplexer.selectedKeys();
                Iterator<SelectionKey> handleIterator = readyHandles.iterator();
                while (handleIterator.hasNext()) {
                    SelectionKey handle = handleIterator.next();
                    if (handle.isConnectable()) {
                        System.out.println("SelectionKey isConnectable()");
                    }

                    if (handle.isAcceptable()) {
                        System.out.println("SelectionKey isAcceptable()");
                        EventHandler handler = registeredHandlers.get(SelectionKey.OP_ACCEPT);
                        handler.handleEvent(handle);
                    }

                    if (handle.isReadable()) {
                        System.out.println("SelectionKey isReadable()");
                        EventHandler handler = registeredHandlers.get(SelectionKey.OP_READ);
                        handler.handleEvent(handle);
                    }

                    if (handle.isWritable()) {
                        System.out.println("SelectionKey isWriteable()");
                        EventHandler handler = registeredHandlers.get(SelectionKey.OP_WRITE);
                        handler.handleEvent(handle);
                    }
                    handleIterator.remove();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}